/* Metrowerks Standard Library
 * Copyright  1995-2003 Metrowerks Corporation.  All rights reserved.
 *
 * $Date: 2003/01/14 21:39:56 $
 * $Revision: 1.24 $
 */

// sstream

#ifndef _SSTREAM
#define _SSTREAM

/*  sstream synopsis

namespace std
{

template <class charT, class traits = char_traits<charT>, class Allocator = allocator<charT> >
class basic_stringbuf
	: public basic_streambuf<charT,traits>
{
public:
	typedef charT                     char_type;
	typedef typename traits::int_type int_type;
	typedef typename traits::pos_type pos_type;
	typedef typename traits::off_type off_type;
	typedef traits                    traits_type;
	typedef Allocator                 allocator_type;

	//  lib.stringbuf.cons Constructors:
	explicit basic_stringbuf(ios_base::openmode which = ios_base::in | ios_base::out);
	explicit basic_stringbuf(const basic_string<charT,traits,Allocator>& str,
	                         ios_base::openmode which = ios_base::in | ios_base::out);

	//  lib.stringbuf.members Get and set:
	basic_string<charT,traits,Allocator> str() const;
	void str(const basic_string<charT,traits,Allocator>& s);

protected:
	//  lib.stringbuf.virtuals Overridden virtual functions:
	virtual int_type   underflow();
	virtual int_type   pbackfail(int_type c = traits::eof());
	virtual int_type   overflow (int_type c = traits::eof());
	virtual  basic_streambuf<charT,traits>* setbuf(charT*, streamsize);

	virtual pos_type seekoff(off_type off, ios_base::seekdir way,
	                         ios_base::openmode which = ios_base::in | ios_base::out);
	virtual pos_type seekpos(pos_type sp,
	                         ios_base::openmode which = ios_base::in | ios_base::out);
};

typedef basic_stringbuf<char>     stringbuf;
typedef basic_stringbuf<wchar_t> wstringbuf;

template <class charT, class traits = char_traits<charT>, class Allocator = allocator<charT> >
class basic_istringstream
	: public basic_istream<charT, traits>
{
public:
	typedef charT                     char_type;
	typedef typename traits::int_type int_type;
	typedef typename traits::pos_type pos_type;
	typedef typename traits::off_type off_type;
	typedef traits                    traits_type;
	typedef Allocator                 allocator_type;

	//  lib.istringstream.cons Constructors:
	explicit basic_istringstream(ios_base::openmode which = ios_base::in);
	explicit basic_istringstream(const basic_string<charT, traits, Allocator>& str,
		ios_base::openmode which = ios_base::in);

	//  lib.istringstream.members Members:
	basic_stringbuf<charT, traits, Allocator>* rdbuf() const;

	basic_string<charT, traits, Allocator> str() const;
	void str(const basic_string<charT, traits, Allocator>& s);
};

typedef basic_istringstream<char>     istringstream;
typedef basic_istringstream<wchar_t> wistringstream;

template <class charT, class traits = char_traits<charT>, class Allocator = allocator<charT> >
class basic_ostringstream
	: public basic_ostream<charT,traits>
{
public:
	typedef charT                     char_type;
	typedef typename traits::int_type int_type;
	typedef typename traits::pos_type pos_type;
	typedef typename traits::off_type off_type;
	typedef traits                    traits_type;
	typedef Allocator                 allocator_type;

	//  lib.ostringstream.cons Constructors/destructor:
	explicit basic_ostringstream(ios_base::openmode which = ios_base::out);
	explicit basic_ostringstream(const basic_string<charT, traits, Allocator>& str,
		ios_base::openmode which = ios_base::out);

	//  lib.ostringstream.members Members:
	basic_stringbuf<charT, traits, Allocator>* rdbuf() const;

	basic_string<charT, traits, Allocator> str() const;
	void str(const basic_string<charT, traits, Allocator>& s);
};

typedef basic_ostringstream<char>     ostringstream;
typedef basic_ostringstream<wchar_t> wostringstream;

template <class charT, class traits = char_traits<charT>, class Allocator = allocator<charT> >
class basic_stringstream
	: public basic_iostream<charT, traits>
{
public:
	typedef charT                     char_type;
	typedef typename traits::int_type int_type;
	typedef typename traits::pos_type pos_type;
	typedef typename traits::off_type off_type;
	typedef traits                    traits_type;
	typedef Allocator                 allocator_type;

	//  constructors/destructors
	explicit basic_stringstream(ios_base::openmode which = ios_base::out|ios_base::in);
	explicit basic_stringstream(const basic_string<charT, traits, Allocator>& str,
		ios_base::openmode which = ios_base::out|ios_base::in);

	//  Members:
	basic_stringbuf<charT, traits, Allocator>* rdbuf() const;
	basic_string<charT, traits, Allocator> str() const;
	void str(const basic_string<charT, traits, Allocator>& str);
};

typedef basic_stringstream<char>     stringstream;
typedef basic_stringstream<wchar_t> wstringstream;

}  // std
*/

#include <mslconfig>

#ifndef _MSL_NO_IO

#include <istream>
#include <streambuf>
#include <vector>

#ifndef RC_INVOKED

#pragma options align=native

#ifdef _MSL_FORCE_ENUMS_ALWAYS_INT
	#if _MSL_FORCE_ENUMS_ALWAYS_INT
		#pragma enumsalwaysint on
	#else
		#pragma enumsalwaysint off
	#endif
#endif

#ifdef _MSL_FORCE_ENABLE_BOOL_SUPPORT
	#if _MSL_FORCE_ENABLE_BOOL_SUPPORT
		#pragma bool on
	#else
		#pragma bool off
	#endif
#endif

#ifndef _MSL_NO_CPP_NAMESPACE
	namespace std {
#endif

template <class charT, class traits, class Allocator>
class basic_stringbuf
	: public basic_streambuf<charT, traits>
{
	typedef basic_streambuf<charT, traits> base;
public:
	typedef charT                     char_type;
	typedef typename traits::int_type int_type;
	typedef typename traits::pos_type pos_type;
	typedef typename traits::off_type off_type;
	typedef traits                    traits_type;
	typedef Allocator                 allocator_type;


	//  lib.stringbuf.cons Constructors:
	explicit basic_stringbuf(ios_base::openmode which = ios_base::in | ios_base::out);
	explicit basic_stringbuf(const basic_string<charT, traits, Allocator>& str,
		ios_base::openmode which = ios_base::in | ios_base::out);

	//  lib.stringbuf.members Get and set:
	basic_string<charT, traits, Allocator> str() const;
	void str(const basic_string<charT, traits, Allocator>& s);

protected:
	//  lib.stringbuf.virtuals Overridden virtual functions:
	virtual int_type underflow();
	virtual int_type pbackfail(int_type c = traits::eof());
	virtual int_type overflow (int_type c = traits::eof());
	// virtual basic_streambuf<charT, traits>* setbuf(charT*, streamsize); use base class

	virtual pos_type seekoff(off_type off, ios_base::seekdir way,
		ios_base::openmode which = ios_base::in | ios_base::out);
	virtual pos_type seekpos(pos_type sp,
		ios_base::openmode which = ios_base::in | ios_base::out);

private:
	typedef vector<charT, Allocator> buf_type;

	ios_base::openmode mode_;
	buf_type str_;
};

template <class charT, class traits, class Allocator>
class basic_istringstream
	: public basic_istream<charT, traits>
{
public:
	typedef charT                     char_type;
	typedef typename traits::int_type int_type;
	typedef typename traits::pos_type pos_type;
	typedef typename traits::off_type off_type;
	typedef traits                    traits_type;
	typedef Allocator                 allocator_type;

	//  lib.istringstream.cons Constructors:
	explicit basic_istringstream(ios_base::openmode which = ios_base::in);
	explicit basic_istringstream(const basic_string<charT, traits, Allocator>& str,
		ios_base::openmode which = ios_base::in);

	//  lib.istringstream.members Members:
	basic_stringbuf<charT, traits, Allocator>* rdbuf() const;

	basic_string<charT, traits, Allocator> str() const;
	void str(const basic_string<charT, traits, Allocator>& s);
private:
	basic_stringbuf<charT, traits, Allocator> sb_;
};

template <class charT, class traits, class Allocator>
class basic_ostringstream
	: public basic_ostream<charT,traits>
{
public:
	typedef charT                     char_type;
	typedef typename traits::int_type int_type;
	typedef typename traits::pos_type pos_type;
	typedef typename traits::off_type off_type;
	typedef traits                    traits_type;
	typedef Allocator                 allocator_type;

	//  lib.ostringstream.cons Constructors/destructor:
	explicit basic_ostringstream(ios_base::openmode which = ios_base::out);
	explicit basic_ostringstream(const basic_string<charT, traits, Allocator>& str,
		ios_base::openmode which = ios_base::out);

	//  lib.ostringstream.members Members:
	basic_stringbuf<charT, traits, Allocator>* rdbuf() const;

	basic_string<charT, traits, Allocator> str() const;
	void str(const basic_string<charT, traits, Allocator>& s);
private:
	basic_stringbuf<charT, traits, Allocator> sb_;
};

template <class charT, class traits, class Allocator>
class basic_stringstream
	: public basic_iostream<charT, traits>
{
public:
	typedef charT                     char_type;
	typedef typename traits::int_type int_type;
	typedef typename traits::pos_type pos_type;
	typedef typename traits::off_type off_type;
	typedef traits                    traits_type;
	typedef Allocator                 allocator_type;

	//  constructors/destructors
	explicit basic_stringstream(ios_base::openmode which = ios_base::out|ios_base::in);
	explicit basic_stringstream(const basic_string<charT, traits, Allocator>& str,
		ios_base::openmode which = ios_base::out|ios_base::in);

	//  Members:
	basic_stringbuf<charT, traits, Allocator>* rdbuf() const;
	basic_string<charT, traits, Allocator> str() const;
	void str(const basic_string<charT, traits, Allocator>& str);

private:
	basic_stringbuf<charT, traits> sb_;
};

// basic_stringbuf Implementation

template <class charT, class traits, class Allocator>
inline
basic_stringbuf<charT, traits, Allocator>::basic_stringbuf(ios_base::openmode which)
	: mode_(which)
{
}

template <class charT, class traits, class Allocator>
basic_stringbuf<charT, traits, Allocator>::basic_stringbuf(
	const basic_string<charT, traits, Allocator>& str, ios_base::openmode which)
	: str_(str.begin(), str.end(), str.get_allocator()),
	  mode_(which)
{
	typename buf_type::size_type sz = str_.size();
	if (sz > 0)
	{
		charT* p = &str_[0];
		if (mode_ & ios_base::out)
		{
			base::setp(p, p + sz);
			if (mode_ & (ios_base::app | ios_base::ate))
				base::pbump((int)sz);
		}
		if (mode_ & ios_base::in)
			base::setg(p, p, p + sz);
	}
}

template <class charT, class traits, class Allocator>
inline
basic_string<charT, traits, Allocator>
basic_stringbuf<charT, traits, Allocator>::str() const
{
	if (mode_ & ios_base::out)
		return basic_string<charT, traits, Allocator>(base::pbase(), base::epptr(), str_.get_allocator());
	return basic_string<charT, traits, Allocator>(base::eback(), base::egptr(), str_.get_allocator());
}

template <class charT, class traits, class Allocator>
void
basic_stringbuf<charT, traits, Allocator>::str(const basic_string<charT, traits, Allocator>& s)
{
	typename buf_type::size_type sz = s.size();
	str_.assign(s.begin(), s.end());
	charT* p = str_.capacity() != 0 ? &str_.front() : 0;
	if (mode_ & ios_base::out)
	{
		base::setp(p, p + sz);
		if (mode_ & (ios_base::app | ios_base::ate))
			base::pbump((int)sz);
	}
	if (mode_ & ios_base::in)
		base::setg(p, p, p + sz);
}

template <class charT, class traits, class Allocator>
inline
typename basic_stringbuf<charT, traits, Allocator>::int_type
basic_stringbuf<charT, traits, Allocator>::underflow()
{
	return base::gptr() < base::egptr() ? traits::to_int_type(*base::gptr()) : traits::eof();
}

template <class charT, class traits, class Allocator>
typename basic_stringbuf<charT, traits, Allocator>::int_type
basic_stringbuf<charT, traits, Allocator>::pbackfail(int_type c)
{
	if (base::eback() >= base::gptr())
		return traits::eof();
	if (traits::eq_int_type(c, traits::eof()))
	{
		base::gbump(-1);
		return traits::not_eof(c);
	}
	charT ch = traits::to_char_type(c);
	if (!(mode_ & ios_base::out) && !traits::eq(ch, base::gptr()[-1]))
		return traits::eof();
	base::gbump(-1);
	*base::gptr() = ch;
	return c;
}

template <class charT, class traits, class Allocator>
typename basic_stringbuf<charT, traits, Allocator>::int_type
basic_stringbuf<charT, traits, Allocator>::overflow(int_type c)
{
	if (!(mode_ & ios_base::out))
		return traits::eof();
	if (traits::eq_int_type(c, traits::eof()))
		return traits::not_eof(c);
	if (base::pptr() < base::epptr())
	{
		*base::pptr() = traits::to_char_type(c);
		base::pbump(1);
		return c;
	}
	if (str_.size() < str_.capacity())
	{
		str_.resize(str_.size() + 1, traits::to_char_type(c));
		if (mode_ & ios_base::in)
			base::setg(base::eback(), base::gptr(), base::egptr()+1);
		base::setp(base::pbase(), base::epptr()+1);
		base::pbump((int)(base::epptr() - base::pbase()));
		return c;
	}
	#ifndef _MSL_NO_EXCEPTIONS
	try
	{
	#endif
		long inpos = base::gptr() - base::eback();
		long outpos = base::pptr() - base::pbase();
		str_.resize(str_.size() + 1, traits::to_char_type(c));
		typename buf_type::size_type sz = str_.size();
		charT* p = &str_[0];
		if (mode_ & ios_base::in)
			base::setg(p, p + inpos, p + sz);
		base::setp(p, p + sz);
		base::pbump((int)(outpos + 1));
		return c;
	#ifndef _MSL_NO_EXCEPTIONS
	}
	catch (...)
	{
		return traits::eof();
	}
	#endif
}

template <class charT, class traits, class Allocator>
typename basic_stringbuf<charT, traits, Allocator>::pos_type
basic_stringbuf<charT, traits, Allocator>::seekoff(off_type off, ios_base::seekdir way,
	ios_base::openmode which)
{
	ios_base::openmode inout = ios_base::in | ios_base::out;
	if ((which & inout) == inout && way == ios_base::cur || (which & inout) == 0)
		return pos_type(-1);
	if (which & ios_base::in  && !(mode_ & ios_base::in) ||
	    which & ios_base::out && !(mode_ & ios_base::out))
		return pos_type(-1);
	if ((which & ios_base::in)  && base::gptr() == 0 ||
	    (which & ios_base::out) && base::pptr() == 0)
		return pos_type(-1);
	off_type newoff;
	switch (way)
	{
	case ios_base::beg:
		newoff = 0;
		break;
	case ios_base::cur:
		if (which & ios_base::out)
			newoff = base::pptr() - base::pbase();
		else
			newoff = base::gptr() - base::eback();
		break;
	case ios_base::end:
		if (mode_ & ios_base::out)
			newoff = base::epptr() - base::pbase();
		else
			newoff = base::egptr() - base::eback();
		break;
	default:
		return pos_type(-1);
	}
	newoff += off;
	if (newoff < 0 || newoff > str_.size())
		return pos_type(-1);
	if (mode_ & ios_base::app && which & ios_base::out && newoff != str_.size())
		return pos_type(-1);
	if (which & ios_base::in)
		base::setg(base::eback(), base::eback() + newoff, base::egptr());
	if (which & ios_base::out)
	{
		base::setp(base::pbase(), base::epptr());
		base::pbump((int)newoff);
	}
	return pos_type(newoff);
}

template <class charT, class traits, class Allocator>
typename basic_stringbuf<charT, traits, Allocator>::pos_type
basic_stringbuf<charT, traits, Allocator>::seekpos(pos_type sp, ios_base::openmode which)
{
	if ((which & (ios_base::in | ios_base::out)) == 0)
		return pos_type(-1);
	if (which & ios_base::in  && !(mode_ & ios_base::in) ||
	    which & ios_base::out && !(mode_ & ios_base::out))
		return pos_type(-1);
	if ((which & ios_base::in)  && base::gptr() == 0 ||
	    (which & ios_base::out) && base::pptr() == 0)
		return pos_type(-1);
	off_type off = sp;
	if (off < 0 || off > str_.size())
		return pos_type(-1);
	if (mode_ & ios_base::app && which & ios_base::out && off != str_.size())
		return pos_type(-1);
	if (which & ios_base::in)
		base::setg(base::eback(), base::eback() + off, base::egptr());
	if (which & ios_base::out)
	{
		base::setp(base::pbase(), base::epptr());
		base::pbump((int)off);
	}
	return sp;
}

// basic_istringstream Implementation

template <class charT, class traits, class Allocator>
inline
basic_istringstream<charT, traits, Allocator>::basic_istringstream(ios_base::openmode which)
	: basic_istream<charT, traits>(&sb_),
	  sb_(ios_base::openmode(which | ios_base::in))
{
}

template <class charT, class traits, class Allocator>
inline
basic_istringstream<charT, traits, Allocator>::basic_istringstream(
	const basic_string<charT, traits, Allocator>& str, ios_base::openmode which)
	: basic_istream<charT, traits>(&sb_),
	  sb_(str, ios_base::openmode(which | ios_base::in))
{
}

template <class charT, class traits, class Allocator>
inline
basic_stringbuf<charT, traits, Allocator>*
basic_istringstream<charT, traits, Allocator>::rdbuf() const
{
	return const_cast<basic_stringbuf<charT, traits, Allocator>*>(&sb_);
}

template <class charT, class traits, class Allocator>
inline
basic_string<charT, traits, Allocator>
basic_istringstream<charT, traits, Allocator>::str() const
{
	return rdbuf()->str();
}

template <class charT, class traits, class Allocator>
inline
void
basic_istringstream<charT, traits, Allocator>::str(
	const basic_string<charT, traits, Allocator>& s)
{
	rdbuf()->str(s);
}

// basic_ostringstream Implementation

template <class charT, class traits, class Allocator>
inline
basic_ostringstream<charT, traits, Allocator>::basic_ostringstream(ios_base::openmode which)
	: basic_ostream<charT, traits>(&sb_),
	  sb_(ios_base::openmode(which | ios_base::out))
{
}

template <class charT, class traits, class Allocator>
inline
basic_ostringstream<charT, traits, Allocator>::basic_ostringstream(
	const basic_string<charT, traits, Allocator>& str, ios_base::openmode which)
	: basic_ostream<charT, traits>(&sb_),
	  sb_(str, ios_base::openmode(which | ios_base::out))
{
}

template <class charT, class traits, class Allocator>
inline
basic_stringbuf<charT, traits, Allocator>*
basic_ostringstream<charT, traits, Allocator>::rdbuf() const
{
	return const_cast<basic_stringbuf<charT, traits, Allocator>*>(&sb_);
}

template <class charT, class traits, class Allocator>
inline
basic_string<charT, traits, Allocator>
basic_ostringstream<charT, traits, Allocator>::str() const
{
	return rdbuf()->str();
}

template <class charT, class traits, class Allocator>
inline
void
basic_ostringstream<charT, traits, Allocator>::str(
	const basic_string<charT, traits, Allocator>& s)
{
	rdbuf()->str(s);
}

// basic_stringstream Implementation

template <class charT, class traits, class Allocator>
inline
basic_stringstream<charT, traits, Allocator>::basic_stringstream(ios_base::openmode which)
	: basic_iostream<charT, traits>(&sb_),
	  sb_(which)
{
}

template <class charT, class traits, class Allocator>
inline
basic_stringstream<charT, traits, Allocator>::basic_stringstream(
	const basic_string<charT, traits, Allocator>& str, ios_base::openmode which)
	: basic_iostream<charT, traits>(&sb_),
	  sb_(str, which)
{
}

template <class charT, class traits, class Allocator>
inline
basic_stringbuf<charT, traits, Allocator>*
basic_stringstream<charT, traits, Allocator>::rdbuf() const
{
	return const_cast<basic_stringbuf<charT, traits, Allocator>*>(&sb_);
}

template <class charT, class traits, class Allocator>
inline
basic_string<charT, traits, Allocator>
basic_stringstream<charT, traits, Allocator>::str() const
{
	return rdbuf()->str();
}

template <class charT, class traits, class Allocator>
inline
void
basic_stringstream<charT, traits, Allocator>::str(
	const basic_string<charT, traits, Allocator>& s)
{
	rdbuf()->str(s);
}

#ifndef _MSL_NO_CPP_NAMESPACE
	} // namespace std
#endif

#ifdef _MSL_FORCE_ENUMS_ALWAYS_INT
	#pragma enumsalwaysint reset
#endif

#ifdef _MSL_FORCE_ENABLE_BOOL_SUPPORT
	#pragma bool reset
#endif

#pragma options align=reset

#endif  // RC_INVOKED

#endif // _MSL_NO_IO

#endif  // _SSTREAM

// hh 971220 fixed MOD_INCLUDE
// hh 971223 Changed filename from sstream.h to sstream
// hh 971223 Made include guards standard
// hh 971223 added alignment wrapper
// hh 971230 added RC_INVOKED wrapper
// hh 980129 changed <istream> from <iostream>
// hh 980810 plugged memory leak by commenting out init in constructors.
//           init is called by the base classes.
// hh 980904 fixed string_type
// hh 981220 Added typename to appropriate return types
// hh 990119 Rewrote.
// hh 990825 Reversed order of top two tests in overflow.  Author of this part of standard
//           (Jerry Schwarz) says that this was intent.
// hh 001011 Fixed bug several places:  base class missing template arguments
// hh 010402 Removed 68K CMF support
// hh 010508 Added allocator_type typedef to all classes (issue 251)
// hh 010820 Added cast to pbump calls
// hh 011005 Corrected & precedence bug in error test in seekpos
// hh 011010 seekpos and seekoff now check for null next pointer case
